Practice1_HelloWorld

目标:启动一个Android应用,在界面显示Hello World

问题1:使用Android Studio模拟器无法进行调试

解决方法:由于使用安卓原生的模拟器无法进行调试,所以尝试安装使用Genymotion模拟器,安装完Genymotion模拟器之后用于系统设置的原因以及VirtualBox虚拟机的原因,也无法调试,最后采用了真机调试的方法。使用测试的手机是Android5.0,最大支持的API等级是21,所以无法使用Android7.0的24。

Practice2_Logcat

目标:学习使用Logcat来调试应用程序

问题1:不清楚Logcat的作用

解决方法:刚开始使用Logcat的时候,并不清楚如何调试,也不知道Log.d()或者Log.e()等一些方法的作用和它们的参数是什么意思。只是觉得和java的System.out.println()作用相似。后来在Logcat的界面,发现了Filter这个东西,知道了这是一个过滤器,通过设置过滤器,能够对于指定的Log进行输出,同时也能够按照等级进行过滤。过滤器的Log Tag值对应于Log.d(TAG,"Debug").第一个参数,只有第一个参数和Log Tag相匹配的Log语句才能够输出,可以选择使用正则表达式(Regex)的形式进行匹配,功能非常的灵活和强大优先级如下:


     Error>Warn>Info>Debug>Verbose

Practice3_Component

目标:熟悉Android提供的一些组件,包括按钮、输入域、文本域等组件。

问题1:R文件找不到

解决方法:这个问题花费了很长时间,通过上网搜发现这个问题一些情况:
(1)xml文件出错,包括布局文件、配置文件等xml文件出错.
(2)可能是由于project进行build时出错,点击Android Stuido上方的Build选项,再点击Rebuild Project。
第一种情况比较常见,然后我仔细检查了刚写的布局文件,并没有发现有什么错误,编辑器也没有报错误,然后我点击了Rebuild Project之后,R文件就找到了。

问题2:使用RadioButton实现单选按钮,但是两个都能被同时选中。

解决方法:通过查阅资料知道了Rradio Button必须放在一个RadioGroup里面,才能实现单选,才能作为一组选项存在,不然就会被认为是两个单选按钮,每个里面选项只有一个。所以必须将RadioButton放在一个Group里面。

Practice4_ListView

目标:使用List View来实现多项数据的显示

问题1:对于List View显示数据以及用什么方式显示数据比较陌生。

解决方法:给List View 显示数据需要使用一个Adapter来进行适配。可以选择的适配器有很多种,有ArrayAdapter、SimpleAdapter以及自定义的Adapter。这次的练习是使用SimpleAdapter,首先看一下Simple Adapter的构造方法:
simpleAdapter = new SimpleAdapter(this,arrayList,R.layout.list_item,new String[] {"name","classno","id"},new int[]{R.id.name,R.id.classno,R.id.id});
在构造方法里可以看见一共有5个参数,第一个是上下文环境,在Activity中传入this,第二个参数是要显示的数据,参数类型是一个List<Map<String,String>>,ListView的每一项的数据其实就是List中的一个Map的值,每一个值都有一个键来对应。第三个参数是一个布局文件的,通过这个布局文件,定义这个List View的每一项如何进行显示。第四个参数和第五个参数是一一对应的关系,顺序进行对应。第四个参数的内容是在Map中保存的键,第五个参数是第三个参数所引入的布局,用于显示数据的ID。也就是说,第四个参数的键,所对应的值显示在第五个参数指定的ID所对应的组件上。知道了这些信息之后,就知道了ListView是如何适配数据的。在这里也感觉到了Android的强大。

Practice5_RecyclerView

目标:使用Recycler View控件进行多项数据的显示

问题1:RecyclerView和ListView的区别是什么?

解决方法:这个问题通过查阅资料我知道了RecyclerView所实现的功能和ListView实现的功能大致是相同的,同时为了解决有多项数据进行显示的问题。RecyclerView可以理解成是一种更加灵活的ListView,他可以自己定义很多东西,包括布局,有流式布局、瀑布布局等等。但是RecyclerView使用起来要比ListView更加的麻烦,或者说复杂,他需要自己定义很多东西,包括它的适配器,以及在定义适配器时,需要实现一个ViewHolder来实现想要显示的东西。

问题2:RercyclerView是如何实现的?

解决方法:首先需要自己写一个RecyclerView.Adapter的派生类,作为RecyclerView的适配器,主要是为了使用ViewHolder。然后重写其中的onCreateView()、onBindViewHolder()等方法。在onCreateViewHolder()中,返回值是一个ViewHolder(这个Holder也是需要自己写一个派生类,在ViewHolder的派生类中写构造方法,用于显示数据的空间),返回的ViewHolder包含了定义了RecyclerView中的某一项的显示方法的View。
在onBindViewHolder()中,设置了数据的显示,给holder中找到的View设置数据。这一切都是Android提供了完整的回调方法来完成。
完成了派生的Adapter之后,剩下的操作和ListView非常的类似,创建一个Adapter的实例,然后给RecyclerView的对象设置adapter,传入参数即可。
从这里可以看出,Android的运作方式基本上都是采用了回调的方式,我们只需要完成某一些模块、某一些特定的功能即可,使用起来非常的方便。

问题:在用到recyclerView的时候,发现怎么也找不到这个类。

解决:一开始用什么办法都不好使,上网查阅解决方法得知应该在AndroidStudio中,点击file\projectStructure,点击对应的moudle,右侧上方选择Dependences,在下方右侧点击绿色的‘+’,找到recyclerView的包,然后进行导入操作。

Practice6_Menu

目标:学习使用OptionMenu和ContextMenu

问题1:长按一个控件无法显示ContextMenu

解决方法:原因是我没有为控件进行注册,没有调用registerForContextMenu(View view)这个方法,所以长按没法显示出Context Menu,只是重写了OnCreateContextMenu()和OnContextItemSelected()这两个方法,是由于粗心犯的错误。

Practice7_Dialog

目标:使用Dialog,实现点击按钮,弹出一个登陆窗口和一个提示窗口。

问题1:Dialog中的布局需要自己写,不需要写确定取消按钮。

解决方法;这个问题就是因为对android系统不熟悉,Dialog中的布局,如果想使用一种比较复杂的布局,需要自己提前再layout中写好,然后再加载布局。对于确定取消按钮,Dialog都有提供的setPositiveButton()和setNegativeButton()这两种,所以不需要自己写,添加上监听事件就可以。

问题2:输入正确的账号密码但是无法正常显示,也没有报错。

解决方法:这个问题就涉及到了对于inflater.inflate()这个方法的认识了,一开始的时候,我先通过inflater,调用了一次加载,生成了一个View对象,然后作为对话框要显示的界面,但是我在处理点击事件的时候,又一次的调用了inflater.inflate()方法,生成了第二个view,然后得到了输入账号和密码的EditText,使用了从第二个View得到的EditText,进行数据的验证。由于对这个方法认识不正确,我以为只会有一个View加载出来,但是实际上是每调用一次,就会生成一个View,所以我数据验证的其实是在另一个View,而真正使用的View,两个EditText都是空值,所以验证失败。这个问题是通过了多尝试几次,以及尝试不同的值发现的问题。

Practice14_IntentFilter

目标:掌握使用Intent隐式启动的方法。

知识点:AndroidManinifest.xml中的每个Activity中,如果设置了元素的话,系统就会将要求同相比较,如果匹配的话就说明这个Activity满足要求,启动这个Activity。

问题:实验中遇到了不能启动第二个Activity的问题。

解决:开始时检查到在AndroidManifest确实配置了activity的action属性,但是还是不能启动第二个Activity,通过上网查阅资料,原来是因为在intent-filter中只配置了action属性,而没有写category属性,加上category属性即可。在隐式Intent中,用户并没有明确指出要启动哪个组件,仅是对要启动的组件提出要求,只有 满足要求的组件才会被Android系统启动。
如果通过startActivity()隐式启动一个Activity(该Activity不是MAIN或LAUNCHER等)的话, 则要求该Activity至少有一个name为"android.intent.category.DEFAULT"的Category,否则将 会导致Intent匹配失败,从而不能成功启动该Activity。

Practice15_Telephone

目标:掌握使用Intent拨打电话。

知识点:data和type属性也可以用来隐式启动组件。需要修改MainActivity中OnCreate()
Intent.ACTION_CALL能打开电话应用程序并拨打指定的电话号码。

问题:当使用直接拨打的action时,使用android.intent.action.CALL后面接的参数是要拨打的电话号码。但是一直都无法直接拨打。

解决:直接使用CALL是由于权限的问题,已经无法直接打出,所以需要修改action设为android.intent.action.DIAL先跳转到拨打电话的页面,然后点击拨打才能打出电话号。

Practice16_DeepUnderstandIntentFilter

目标:进一步熟悉Intent Filter。

知识点:AndroidManifest.xml文件中每个组件的都被解析成一个Intent过滤器对象。当应用程序安装到Android系统时,所有的组件和Intent过滤器都会注册到Android系统中。
这样,Android系统便可以将任何一个Intent请求通过Intent过滤器映射到相应的组件上。

问题:程序一直报如下的错误:

解决:一开始想了半天没想到解决办法,结果后来发现原来是将Uri.parse()中http地址写错了,改成如下地址即可:

Practice20_SQLite

目标:掌握Android中对SQLite数据库进行操作的相关类和方法,实现单词本,实现对单词的增、删、改、查等。

知识点:数据库操作使用了SQLiteOpenHelper。首先从SQLiteOpenHelper派生了WordsDBHelper类,然后重写了该类的OnCreate()方法和onUpgrade()方法。在OnCrete()方法中创建数据库中的words表,在onUpgrade()中删除旧表,然后调用OnCreate()再次创建新表。

问题:实验中sqlite一直提示“ the database file is locked ”

解决:几经检查发现是因为调用了SQLiteDataReader对象,却忘记把它关闭掉,关闭即可。

Practice22_Contacter

目标:本实验主要是了解系统ContentProvider基本概念。

知识点:要想访问联系人,必须设置读或写的权限,如下:

在Android系统中,联系人应用程序为“Contacts”,该程序是一个 ContentProvider,提供了供其它程序访问和操控的“界面”,方便其它程序使用。
联系人id、联系人名称(display_name)、最后的通话时间、通话记录次数等信息就存放在 contacts表中。幸好contacts程序提供了提供了用于管理联系人的Uri方便其它程序访问,下面 给出几个常用的Uri:
(1)ContactsContract.Contacts.CONTENT_URI:联系人
(2)ContactsContract.CommonDataKinds.Phone.CONTENT_URI:电话,所指向的值其实 是“content:// com.android.contacts/data/phones”,这个Uri会访问contacts表、 raw_contacts 表和data表等。 (3)ContactsContract.CommonDataKinds.Email.CONTENT_URI:邮件

问题:运行程序总是报如下图的错误:

解决:对于安卓的一些额外的操作比如读取联系人或者访问等,安卓系统为了安全所以提供了一些权限的控制来进行系统的保护。读取联系人就是其中的一项。所以想要访问手机卡中的联系人,就需要在manifest中增加读取联系人的权限,如下图:

Practice23_ContentObserver

目标:掌握ContentObserver基本概念,主要是实现监控联系人发生改变时情况。

知识点:Android系统提供ContentObserver来实现监听功能。实现监听功能包括:注册和重写onChange()。Android系统提供ContentObserver来实现监听功能。实现监听功能包括以下几个步骤:
1.注册。通知Android系统应用程序对于某个Uri感兴趣,如果该Uri对应的ContenProvider数据 发生改变,Android系统会自动调用ContentObserver的onChange方法,这非常类似于数据库 中触发器。 public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer) 其中uri为需要监听的ContentProvider所对应的Uri。 notifyForDescendents为false时表示精确匹配,为true时表示同时匹配派生的Uri。
2.重写ContentObserver的onChange方法,在此方法读取改变的内容,然后再做进一步地处 理。

注意:需要有访问联系人的权限。

问题:实验中运行程序的时候打不开。

解决:经过检查是因为在AndroidManifest.xml函数中缺少权限值,在代码需要加入下面两行代码:

Practice24_StartService

目标:掌握Service基本特点和startService启动服务方法。

知识点:首先我们明白Service是Android系统的服务组件,适用于开发没有用户界面且长时间在后台运行的应用功能。Service是Android四大组件之一,但是同Activity最大的区别是Service没有用户界面。当第一启动Service时,启动Service,并同时把一个整数传递过去,由于Service原来并没有创建,因此创建并启动该Service,依次回调onCreate()、onStartCommand()方法,在onStartCommand()方法中接收传过来的整数,如想要Service做一些其它事情,也可以在onStartCommand()方法中去实现。当第二次启动Service,Service由于已经运行,因此并不调用onCreate(),而仅回调onStartCommand(),当停止Service时,回调onDestroy()方法。

注意:通过startservice启动的服务无法和Activity进行交互,Service一经启动之后就无法关闭。

问题:实验中startService(intent)没有执行service的onStartCommand()。

解决:经过检查发现因为我只是简单的注册了service ,并没有给这个service起个名字,这样调用是启动不了service的,在manifest中加个别名即可,如下图:

Practice26_Handler

目标:使用Handler在新线程中发送消息,然后在主线程中处理消息,学会使用handler处理消息。

知识点:首先我们要明白Handler出现的原因:当应用程序启动时,Android首先会开启一个主线程为管理界面中的UI控件。如果此时需要一个耗时的操作,就不能把这些操作放在主线程中,否则会出现界面假死现象,我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的,基于这种情况,Handler就出现了,由于Handler运行在主线程中,它与子线程可以通过Message对象来传递数据,Handler就承担着接受子线程传过来的Message对象,把这些消息放入主线程队列中,配合主线程进行更新UI。
Hanlder的主要用法是在新线程中发送消息,然后在主线程中处理消息,在线程中每秒产生一个数字,然后通过Hander.sendMessage(Message)将消息发送给主线程,在主线程Handler.handleMessage()中接收并处理该消息,使用Handler的post()方法将Runnable对象从后台线程发送给主线程。
Handler一些特点
handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),它有两个作用:
(1)安排消息或Runnable 在某个主线程中某个地方执行;
(2)安排一个动作在不同的线程中执行。

问题:在主线程handlemessage中接收不到消息

解决:因为在子线程中所使用的Handler并不是从Activity传过去的,而是调用handler的构造方法,new handler(Looper.getMainLooper())方法来得到。这样就相当于是向不同的Handler发送的数据。无法在主线程中的Handler对象中接收到。

Practice28_MediaPlayer

目标:能够使用MediaPalyer实现音乐播放器,包括播放、暂停、停止等功能。

知识点:MediaPlayer提供了一系列的设置事件监听器的方法,当MediaPlayer状态发生改变或者发生错误时,用户便可以监听这些事件。MediaPlayer的主要方法有: static MediaPlayer create(Context context, Uri uri):使用并装载 给定的uri来创建MediaPlayer对象。 void prepare():准备播放。 void start():开始或恢复播放。 void pause():暂停播放。 void stop():停止播放。 void reset():初始化。 void release():释放 MediaPalyer对象申请的资源。 void setLooping(boolean looping):设置循环播放。 void seekTo(int msec):跳转到指定时间位置。 void setVolume(float leftVolume, float rightVolume):设置声音大小。

问题:运行程序的时候,遇到了activity关闭后 音乐播放也随之停止的问题。

解决:原因是在退出的时候按了home键 然后清理程序,服务随之消失了,正确做法是按后退键则正常播放。

Practice29_TakePhoto

目标:熟悉Android里面拍照相关方法。能够实现拍照、把照片保存为文件。

知识点:使用相机,必须要添加相应请求。

使用Intent执行拍照注意在调用startActivityForResult()方法之前,先调用resolveActivity(), 这个方法会返回能处理该Intent的第一个Activity(即检查有没有能处理这个Intent的 Activity)。执行这个检查非常重要,因为如果在调用startActivityForResult()时,没有应用能 处理你的Intent,应用将会崩溃。所以只要返回结果不为null,使用该Intent就是安全的。
如果想要照片的全尺寸照片,而不是缩略图,则必须给出一个路径,android系统会将照片保 存到该路径下。路径一般位于外部存储卡中。最常用的是将路径放到公共图片目录中,这样 每个应用程序都可以访问。公共图片路径目录可以通过 getExternalStoragePublicDirectory(DIRECTORY_PICTURES)方法获得。另外还要记得给应 用程序添加访问外部存储卡的权限。
如果希望照片只能够自己访问,则可以使用getExternalFilesDir()来获得目录。

问题:横竖屏问题,即照出来的照片会旋转,如何能够实现照出来的照片不会旋转。

解决:通过上网查阅资料得知需要在onCreate内加上一句
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);强制为横屏即可。

Practice30_DrawPicture

目标:熟悉自定义View方法,能够编程绘制简单图形。

知识点:生成一个从View派生的类,然后重写该类的onDraw()方法,在此方法中绘制。为了实现绘制,应用程序至少需要4个组件:Bitmap(位图,用来存储像素),Canvas(画布,实现在位图上绘制),基本图元(Rect、Path、text、Bitmap等),Paint(画笔,描述颜色和图型等)。可以调用invalidate()方法对图形进行重新绘制或刷新。

问题:在使用自定义view时,无法显示出自定义的view的图形,并且在preview窗口提示渲染错误,如下图:

解决:自定义view的构造方法参数只有一个,而应该有2-3个方法,使用默认提供的具有多个参数的构造方法。

results matching ""

    No results matching ""